home *** CD-ROM | disk | FTP | other *** search
- (***************************************************************************
-
- $RCSfile: OCI.mod $
- Description: Common routines used by modules OCE, OCP, OCH and Compiler
-
- Created by: fjc (Frank Copeland)
- $Revision: 5.8 $
- $Author: fjc $
- $Date: 1995/01/26 00:17:17 $
-
- Copyright © 1993-1995, Frank Copeland
- This module forms part of the OC program
- See OC.doc for conditions of use and distribution
-
- Log entries are at the end of the file.
-
- ***************************************************************************)
-
- <* STANDARD- *> <* MAIN- *> <*$ LongVars+ *>
-
- MODULE OCI;
-
- IMPORT OCM, OCS, OCT, OCC;
-
- (* --- Local declarations ----------------------------------------------- *)
-
- CONST
-
- (* object modes *)
-
- Var = OCM.Var; VarX = OCM.VarX; Ind = OCM.Ind; IndX = OCM.IndX;
- RegI = OCM.RegI; RegX = OCM.RegX; Lab = OCM.Lab; LabI = OCM.LabI;
- Con = OCM.Con; Push = OCM.Push; Pop = OCM.Pop; Coc = OCM.Coc;
- Reg = OCM.Reg; Fld = OCM.Fld; Typ = OCM.Typ; Abs = OCM.Abs;
- XProc = OCM.XProc; LProc = OCM.LProc; Undef = OCM.Undef;
-
- addressableSet =
- {Var, VarX, Ind, IndX, Reg, RegI, RegX, Con, XProc, LProc};
-
- (* structure forms *)
-
- Char = OCT.Char; DynArr = OCT.DynArr;
-
- (* CPU Registers *)
-
- D0 = 0; D1 = 1; D7 = 7; A0 = 8; A3 = 11; A4 = 12; A5 = 13; A6 = 14;
- A7 = 15; BP = A4 - 8; FP = A5 - 8; SP = A7 - 8;
- DataRegs = {D0 .. D7};
- AdrRegs = {A0 .. A7};
-
- (* Data sizes *)
-
- B = 1; W = 2; L = 4;
-
- (* CONST mname = "OCI"; *)
-
- (* --- Procedure declarations ------------------------------------------- *)
-
- (*------------------------------------*)
- PROCEDURE IsParam * (obj : OCT.Object) : BOOLEAN;
-
- BEGIN (* IsParam *)
- RETURN (obj # NIL) & (obj.mode <= Ind) & (obj.a0 >= 0)
- END IsParam;
-
- (*------------------------------------*)
- (*
- Explicitly frees any registers used by x
- *)
- PROCEDURE Unload * (VAR x : OCT.Item);
-
- (* CONST pname = "Unload"; *)
-
- BEGIN (* Unload *)
- (* OCM.TraceIn (mname, pname); *)
- IF x.mode IN {VarX, IndX, Reg, RegI, RegX, Push, Pop} THEN
- OCC.FreeReg (x);
- END
- (* ;OCM.TraceOut (mname, pname); *)
- END Unload;
-
- (*------------------------------------*)
- PROCEDURE Load * (VAR x : OCT.Item);
-
- (* CONST pname = "Load"; *)
-
- VAR y : OCT.Item;
-
- BEGIN (* Load *)
- (* OCM.TraceIn (mname, pname); *)
- IF x.mode < Reg THEN
- y := x; OCC.GetDReg (x); OCC.Move (y.typ.size, y, x); Unload (y)
- ELSIF x.mode > Reg THEN
- OCS.Mark (126); OCS.Warn (2); OCS.Warn (x.mode)
- END
- (* ;OCM.TraceOut (mname, pname); *)
- END Load;
-
- (*------------------------------------*)
- PROCEDURE EXT * (size, reg : LONGINT);
-
- (* CONST pname = "EXT"; *)
-
- BEGIN (* EXT *)
- (* OCM.TraceIn (mname, pname); *)
- IF size = L THEN OCC.PutWord (OCC.EXTL + SHORT (reg))
- ELSE OCC.PutWord (OCC.EXTW + SHORT (reg))
- END
- (* ;OCM.TraceOut (mname, pname); *)
- END EXT;
-
- (*------------------------------------*)
- PROCEDURE DescItem * (VAR item : OCT.Item; desc : OCT.Desc; adr : LONGINT);
-
- (* CONST pname = "DescItem"; *)
-
- BEGIN (* DescItem *)
- (* OCM.TraceIn (mname, pname); *)
- IF desc = NIL THEN
- OCS.Mark (963);
- item.lev := 0; item.mode := Var;
- item.a0 := 0; item.a1 := 0; item.a2 := 0
- ELSE
- (* item = bound descr *)
- item.lev := desc.lev; item.mode := desc.mode; item.a0 := desc.a0;
- item.a1 := desc.a1; item.a2 := desc.a2;
- IF item.mode IN {Var, VarX} THEN INC (item.a0, adr)
- ELSIF item.mode IN {Ind, IndX, RegI, RegX} THEN INC (item.a1, adr)
- ELSE OCS.Mark (322)
- END
- END;
- item.desc := desc; item.typ := OCT.linttyp; item.wordIndex := FALSE
- (* ;OCM.TraceOut (mname, pname); *)
- END DescItem;
-
- (*------------------------------------*)
- PROCEDURE UpdateDesc * (VAR x : OCT.Item; adr : LONGINT);
-
- (* CONST pname = "UpdateDesc"; *)
-
- VAR desc : OCT.Desc;
-
- BEGIN (* UpdateDesc *)
- (* OCM.TraceIn (mname, pname); *)
- desc := x.desc;
- IF desc # NIL THEN
- desc.lev := x.lev; desc.mode := x.mode; desc.a0 := x.a0;
- desc.a1 := x.a1; desc.a2 := x.a2;
- IF desc.mode IN {Var, VarX} THEN DEC (desc.a0, adr)
- ELSIF desc.mode IN {Ind, IndX, RegI, RegX} THEN DEC (desc.a1, adr)
- ELSE OCS.Mark (322)
- END
- END
- (* ;OCM.TraceOut (mname, pname); *)
- END UpdateDesc;
-
- (*------------------------------------*)
- PROCEDURE UnloadDesc * (VAR x : OCT.Item);
-
- (* CONST pname = "UnloadDesc"; *)
-
- VAR desc : OCT.Desc;
-
- BEGIN (* UnloadDesc *)
- (* OCM.TraceIn (mname, pname); *)
- desc := x.desc;
- IF (desc # NIL) & (desc.mode IN {VarX, IndX, RegI, RegX}) THEN
- IF desc.mode # x.mode THEN
- IF desc.mode IN {RegI, RegX} THEN
- OCC.UnReserveReg (SHORT (desc.a0))
- END;
- IF desc.mode IN {VarX, IndX, RegX} THEN
- OCC.UnReserveReg (SHORT (desc.a2))
- END
- ELSE
- IF desc.mode IN {RegI, RegX} THEN
- IF desc.a0 # x.a0 THEN OCC.UnReserveReg (SHORT (desc.a0)) END
- END;
- IF desc.mode IN {VarX, IndX, RegX} THEN
- IF desc.a2 # x.a2 THEN OCC.UnReserveReg (desc.a2) END
- END;
- END
- END
- (* ;OCM.TraceOut (mname, pname); *)
- END UnloadDesc;
-
- (*------------------------------------*)
- PROCEDURE Adr * (VAR x : OCT.Item);
-
- (* CONST pname = "Adr"; *)
-
- VAR
- reg, len, y : OCT.Item; module : OCT.Module; off : LONGINT;
- dreg : INTEGER; wordIndex : BOOLEAN;
-
- (*------------------------------------*)
- PROCEDURE Multiply (VAR lhs, rhs : OCT.Item);
-
- (* CONST pname = "Multiply"; *)
-
- VAR R : SET;
-
- BEGIN (* Multiply *)
- (* OCM.TraceIn (mname, pname); *)
- OCC.LoadRegParams2 (R, lhs, rhs);
- OCC.CallKernel (OCC.kMul32);
- OCC.RestoreRegisters (R, lhs);
- Unload (rhs)
- (* ;OCM.TraceOut (mname, pname); *)
- END Multiply;
-
- BEGIN (* Adr *)
- (* OCM.TraceIn (mname, pname); *)
- IF x.mode IN addressableSet THEN
- IF (x.mode = Con) & (x.typ # OCT.stringtyp) THEN OCS.Mark (127)
- ELSIF x.typ.form = DynArr THEN
- len.mode := Undef;
- IF x.mode IN {IndX, RegX} THEN
- reg.mode := Reg; reg.a0 := x.a2; reg.typ := OCT.linttyp;
- END;
- WHILE x.typ.form = DynArr DO
- IF x.mode IN {IndX, RegX} THEN
- DescItem (len, x.desc, x.typ.adr); Multiply (reg, len)
- END;
- x.typ := x.typ.BaseTyp
- END;
- Unload (len);
- IF x.mode = Var THEN x.mode := Ind; x.a1 := 0 END;
- Adr (x)
- ELSIF x.mode = Reg THEN
- IF x.a0 IN DataRegs THEN OCS.Mark (127) END
- ELSIF x.mode = Con THEN
- IF x.a1 < 3 THEN OCC.AllocStringFromChar (x) END;
- x.mode := LabI; x.a1 := 4
- ELSIF x.mode = Var THEN
- y := x; OCC.GetAReg (x); OCC.PutF2 (OCC.LEA, y, x.a0); Unload (y)
- ELSIF x.mode = VarX THEN
- dreg := x.a2; wordIndex := x.wordIndex;
- y := x; y.mode := Var; y.a2 := 0;
- OCC.GetAReg (x); OCC.PutF2 (OCC.LEA, y, x.a0); Unload (y);
- y.mode := RegX; y.a0 := x.a0; y.a1 := 0; y.a2 := dreg;
- y.wordIndex := wordIndex;
- OCC.PutF2 (OCC.LEA, y, x.a0); OCC.UnReserveReg (dreg)
- ELSIF x.mode = Ind THEN
- IF x.a1 = 0 THEN x.mode := Var
- ELSE
- y := x; y.mode := Var; OCC.GetAReg (reg); reg.desc := x.desc;
- OCC.Move (L, y, reg); Unload (y);
- y.mode := RegI; y.a0 := reg.a0; y.a1 := x.a1; x := reg;
- OCC.PutF2 (OCC.LEA, y, x.a0)
- END
- ELSIF x.mode = IndX THEN
- off := x.a1; dreg := x.a2; wordIndex := x.wordIndex;
- y := x; y.mode := Var; y.a2 := 0;
- OCC.GetAReg (x); OCC.Move (L, y, x); Unload (y);
- IF off # 0 THEN
- y.mode := RegI; y.a0 := x.a0; y.a1 := off;
- OCC.PutF2 (OCC.LEA, y, x.a0)
- END;
- y.mode := RegX; y.a0 := x.a0; y.a1 := 0; y.a2 := dreg;
- y.wordIndex := wordIndex;
- OCC.PutF2 (OCC.LEA, y, x.a0); OCC.UnReserveReg (dreg);
- x.mode := Reg
- ELSIF x.mode = RegI THEN
- IF x.a1 # 0 THEN OCC.PutF2 (OCC.LEA, x, x.a0) END;
- x.mode := Reg; x.a1 := 0
- ELSIF x.mode = RegX THEN
- y := x; x.mode := Reg; x.a1 := 0; x.a2 := 0;
- OCC.PutF2 (OCC.LEA, y, x.a0); OCC.UnReserveReg (y.a2)
- ELSIF x.mode IN {LProc, XProc} THEN
- x.mode := LabI; x.a0 := 0; x.a1 := 4; x.label := x.obj.label
- END;
- IF x.mode = Reg THEN x.a1 := 0; x.a2 := 0; x.obj := NIL END
- ELSE
- OCS.Mark (127)
- END
- (* ;OCM.TraceOut (mname, pname); *)
- END Adr;
-
- (*------------------------------------*)
- PROCEDURE LoadAdr * (VAR x : OCT.Item);
-
- (* CONST pname = "LoadAdr"; *)
-
- VAR y : OCT.Item;
-
- BEGIN (* LoadAdr *)
- (* OCM.TraceIn (mname, pname); *)
- Adr (x);
- IF x.mode # Reg THEN y := x; OCC.GetAReg (x); OCC.Move (L, y, x) END;
- x.mode := RegI; x.a1 := 0; x.a2 := 0; x.obj := NIL
- (* ;OCM.TraceOut (mname, pname); *)
- END LoadAdr;
-
- (*------------------------------------*)
- (*
- Move the address of a variable, procedure or string constant to the
- specified location.
- *)
- PROCEDURE MoveAdr * (VAR x, y : OCT.Item);
-
- (* CONST pname = "MoveAdr"; *)
-
- VAR
- z : OCT.Item; module : OCT.Object; off : LONGINT; reg : INTEGER;
- wordIndex : BOOLEAN;
-
- BEGIN (* MoveAdr *)
- (* OCM.TraceIn (mname, pname); *)
- IF x.mode IN addressableSet THEN
- IF x.mode = Reg THEN
- IF x.a0 < A0 THEN OCS.Mark (127)
- ELSE OCC.Move (L, x, y)
- END
- ELSIF (y.mode = Reg) & (y.a0 >= A0) THEN
- IF x.typ.form = DynArr THEN Adr (x); OCC.Move (L, x, y)
- ELSIF x.mode = Reg THEN OCC.Move (L, x, y)
- ELSIF x.mode = Ind THEN
- z := x; z.mode := Var; OCC.Move (L, z, y);
- IF z.a1 # 0 THEN
- z.mode := RegI; z.a0 := y.a0; OCC.PutF2 (OCC.LEA, z, y.a0)
- END
- ELSIF x.mode = IndX THEN
- off := x.a1; reg := x.a2; wordIndex := x.wordIndex;
- z := x; z.mode := Var; OCC.Move (L, z, y);
- z.mode := RegX; z.a0 := y.a0; z.a1 := off; z.a2 := reg;
- z.wordIndex := wordIndex;
- OCC.PutF2 (OCC.LEA, z, y.a0)
- ELSIF x.mode IN {LProc, XProc} THEN
- x.mode := Lab; x.a0 := 0; x.a1 := 4; x.label := x.obj.label;
- OCC.PutF2 (OCC.LEA, x, y.a0)
- ELSE
- OCC.PutF2 (OCC.LEA, x, y.a0)
- END
- ELSE
- Adr (x); OCC.Move (L, x, y)
- END
- ELSE
- OCS.Mark (127)
- END
- (* ;OCM.TraceOut (mname, pname); *)
- END MoveAdr;
-
- (*------------------------------------*)
- (*
- Copies count bytes from src to dst and then terminates dst with a NUL.
- *)
- PROCEDURE CopyString *
- ( VAR src, dst, count : OCT.Item );
-
- (* CONST pname = "CopyString"; *)
-
- VAR x : OCT.Item; L0 : INTEGER; i : LONGINT;
-
- BEGIN (* CopyString *)
- (* OCM.TraceIn (mname, pname); *)
- IF (count.mode = Con) & (count.a0 < 5) THEN (* inline the loop *)
- IF count.a0 = 1 THEN
- LoadAdr (dst); dst.mode := Pop; (* LEA <dst>,Ad *)
- IF src.mode = Con THEN src.a0 := src.a2; src.typ := OCT.chartyp END;
- OCC.Move (B, src, dst); (* MOVE.B <src>,(Ad)+ *)
- dst.mode := RegI
- ELSIF count.a0 > 1 THEN
- LoadAdr (src); src.mode := Pop; (* LEA <src>,As *)
- LoadAdr (dst); dst.mode := Pop; (* LEA <dst>,Ad *)
- i := count.a0;
- WHILE i > 0 DO
- OCC.Move (B, src, dst); (* MOVE.B (As),(Ad)+ *)
- DEC (i)
- END;
- dst.mode := RegI
- ELSE (* src is an empty string *)
- IF (dst.typ.form = DynArr) & (dst.mode IN {IndX, RegX}) THEN
- LoadAdr (dst) (* LEA <dst>,Ad *)
- END
- END;
- OCC.PutF1 (OCC.CLR, B, dst) (* CLR.B <dst> *)
- ELSE
- LoadAdr (src); src.mode := Pop; (* LEA <src>,As *)
- LoadAdr (dst); dst.mode := Pop; (* LEA <dst>,Ad *)
-
- IF count.mode = Con THEN
- IF count.a0 > 32767 THEN OCS.Mark (63); count.a0 := 1 END;
- count.typ := OCT.inttyp; DEC (count.a0);
- Load (count); (* MOVE.L <count>,Dc *)
- ELSE
- Load (count); (* MOVE.L <count>,Dc *)
- OCC.PutF7 (OCC.SUBQ, L, 1, count); (* SUBQ.L #1,Dc *)
- OCC.PutWord (6002H); (* BRA.S 2$ *)
- END; (* IF *)
- OCC.Move (B, src, dst); (* 1$ MOVE.B (As)+,(Ad)+ *)
- OCC.PutWord (OCC.DBEQ + SHORT (count.a0));
- OCC.PutWord (-4); (* 2$ DBEQ.W Dc, 1$ *)
- OCC.PutWord (6702H); (* BEQ.S 3$ *)
- dst.mode := RegI; OCC.PutF1 (OCC.CLR, B, dst)(* CLR.B <dst> *)
- END; (* 3$ *)
- (* ;OCM.TraceOut (mname, pname); *)
- END CopyString;
-
- END OCI.
-
- (***************************************************************************
-
- $Log: OCI.mod $
- Revision 5.8 1995/01/26 00:17:17 fjc
- - Release 1.5
-
- Revision 5.8 1995/01/26 00:15:16 fjc
- - Release 1.5
-
- Revision 5.7 1995/01/05 11:36:03 fjc
- *** empty log message ***
-
- Revision 5.6 1995/01/03 21:21:29 fjc
- - Changed OCG to OCM.
-
- Revision 5.5 1994/12/16 17:20:24 fjc
- - Changed Symbol to Label.
-
- Revision 5.4 1994/10/23 16:08:14 fjc
- - Fixed register allocation bug in UnloadDesc().
- - Changed Multiply() to use OCC.CallKernel().
-
- Revision 5.3 1994/09/25 17:47:18 fjc
- - Changed to reflect new object modes and system flags.
-
- Revision 5.2 1994/09/15 10:27:13 fjc
- - Replaced switches with pragmas.
-
- Revision 5.1 1994/09/03 19:29:08 fjc
- - Bumped version number
-
- ***************************************************************************)
-